package com.jzo2o.orders.manager.hander;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.jzo2o.api.trade.RefundRecordApi;
import com.jzo2o.api.trade.dto.response.ExecutionResultResDTO;
import com.jzo2o.api.trade.enums.RefundStatusEnum;
import com.jzo2o.common.constants.UserType;
import com.jzo2o.orders.base.enums.OrderRefundStatusEnum;
import com.jzo2o.orders.base.mapper.OrdersMapper;
import com.jzo2o.orders.base.mapper.OrdersRefundMapper;
import com.jzo2o.orders.base.model.domain.Orders;
import com.jzo2o.orders.base.model.domain.OrdersRefund;
import com.jzo2o.orders.manager.model.dto.OrderCancelDTO;
import com.jzo2o.orders.manager.service.IOrdersManagerService;
import com.jzo2o.orders.manager.service.IOrdersRefundService;
import com.jzo2o.orders.manager.strategy.OrderCancelStrategyManager;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Component
@Slf4j
public class OrdersHandler {


    @Autowired
    private IOrdersRefundService ordersRefundService;

    @Autowired
    private RefundRecordApi refundRecordApi;
    @Autowired
    private IOrdersManagerService  ordersManagerService;

    @Autowired
    private OrdersHandler owner;

    @Autowired
    private OrderCancelStrategyManager orderCancelStrategyManager;



    //系统取消超时订单
    @XxlJob(value = "cancelOverTimePayOrder")
    public void cancelOverTimePayOrder() {
        //思路：查询订单表，根据时间和状态判断查询需要取消的超时订单并返回集合-逻辑：订单状态为未支付，时间为创建时间小于当前时间减15分钟
        //1，查寻需要取消的订单
        List<Orders> ordersList = ordersManagerService.lambdaQuery()
                .eq(Orders::getOrdersStatus, 0)
                .eq(Orders::getPayStatus, 0)
                .lt(Orders::getCreateTime, LocalDateTime.now().minusMinutes(15))
                .last("limit 100")
                .list();
        if(CollUtil.isEmpty(ordersList)){
            //没有需要取消的订单可以直接跳出方法
            return;
        }
        //2，遍历集合，调用取消订单方法
        for (Orders order : ordersList) {
            //2.1，先准备参数
            OrderCancelDTO cancelDTO = new OrderCancelDTO();
            cancelDTO.setId(order.getId());
            cancelDTO.setCurrentUserId(0l);
            cancelDTO.setCurrentUserName("系统");
            cancelDTO.setCurrentUserType(UserType.SYSTEM);
            cancelDTO.setCancelReason("超时未支付");
            orderCancelStrategyManager.cancel(cancelDTO);
        }
    }



    //处理退款订单
    @XxlJob(value = "handleRefundOrders")
    public void handleRefundOrders() {
        /**
         * 处理退款订单思路：（处理表：订单表-主要是退款相关字段，退款记录表（删除从操作））
         * 1，查询退款记录表
         * 2，遍历记录表，依次处理每一条数据
         *   2.1，调用支付服务退款api，获取返回记录，检查退款状态
         *   2.2，若为退款中，则跳出本次循环继续下一条数据
         *   2.3，若为退款成功，或者退款失败,更新订单表中相关退款字段，并删除本条退款记录
         *
         */
        //1，查询退款记录表
        List<OrdersRefund> ordersRefunds = ordersRefundService.queryRefundOrderListByCount(100);
        if(CollUtil.isEmpty(ordersRefunds)){
            throw new RuntimeException("无退款订单");
        }
        //2,遍历记录表，依次处理每条数据
        for (OrdersRefund ordersRefund : ordersRefunds) {
            //2.1，调用支付服务退款api，获取返回记录，检查退款状态
            ExecutionResultResDTO resultResDTO = refundRecordApi.refundTrading(ordersRefund.getTradingOrderNo(), ordersRefund.getRealPayAmount());
            //2.2，若为退款中，则跳出本次循环继续下条数据
            if(resultResDTO.getRefundStatus()== OrderRefundStatusEnum.REFUNDING.getStatus()){
                continue;
            }
            owner.afterRefund(ordersRefund,resultResDTO);
        }
    }

    @Transactional
    public void afterRefund(OrdersRefund ordersRefund, ExecutionResultResDTO resultResDTO) {
        //2.3，若为退款成功，（或退款失败）更新订单表中相关退款字段，并删除本条退款记录
       Orders orders = new Orders();
       orders.setRefundStatus(resultResDTO.getRefundStatus());
       orders.setRefundId(resultResDTO.getRefundId());
       orders.setRefundNo(resultResDTO.getRefundNo());
       boolean b = ordersManagerService.updateById(orders);
       if(b){
            ordersRefundService.removeById(ordersRefund);
       }


    }
}
